﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Kanban.Entity;
using System.Data.SqlClient;

namespace Kanban.Repository
{
    public class QuadroRepository : RepositoryBase
    {

        public List<BurndownItem> GerarGraficoBurndown(int id)
        {
            var parametros = new Dictionary<string, object>();
            parametros.Add("IdQuadro", id);

            string sql = @"DECLARE @TotalPontos DECIMAL(10, 4), 
		                    @TotalDias INT,
		                    @PontosFeitos DECIMAL(10, 4),
		                    @IdAcaoMover INT,
		                    @DataInicio DATETIME,
		                    @DataFim DATETIME,
		                    @PontosPorDia DECIMAL(10, 4),
		                    @UltimoStatus INT = 2 -- Subtraí 1


                    SELECT @IdAcaoMover = Id FROM [PREFIXO_TABELA]LogAcao WHERE Mnemonico = 'TAREFA_MOVER'
                    SELECT @DataInicio = CONVERT(VARCHAR(10), DataInicio, 101), @DataFim = CONVERT(VARCHAR(10), DataFim, 101) FROM Quadro WHERE Id = @IdQuadro
                    SELECT @TotalPontos = COUNT(*) * @UltimoStatus FROM [PREFIXO_TABELA]Tarefa WHERE IdQuadro = @IdQuadro

                    SELECT CONVERT(VARCHAR(10), l.DataCadastro, 101) AS Data, SUM(CAST(ValorNovo AS DECIMAL(10, 4)) - 1) AS Executado 
                    INTO #Log
                    FROM [PREFIXO_TABELA]LogTarefa l
                    INNER JOIN [PREFIXO_TABELA]Tarefa t
                    ON t.Id = l.IdTarefa
                    WHERE t.IdQuadro = @IdQuadro
                    AND l.IdLogAcao = @IdAcaoMover
                    AND t.Excluido = 0 AND l.Excluido = 0
                    GROUP BY CONVERT(VARCHAR(10), l.DataCadastro, 101)

                    SET @TotalDias = DATEDIFF(d, @DataInicio, @DataFim)
                    SET @PontosPorDia =  @TotalPontos / @TotalDias

                    CREATE Table #Burndown(Data DATETIME, Planejado DECIMAL(10, 4), Executado DECIMAL(10, 4))

                    DECLARE @Dia INT = 0, @Valor DECIMAL(10, 4) = 0, @Data DATETIME = @DataInicio
                    WHILE @Data <= @DataFim 
                    BEGIN
		

	                    IF @Data > GETDATE() 
	                    BEGIN
		                    SET @Valor = NULL
	                    END 
	                    ELSE 
	                    BEGIN
		                    IF (SELECT Executado FROM #Log WHERE Data = @Data) IS NOT NULL 
		                    BEGIN
			                    SELECT @Valor = Executado FROM #Log WHERE Data = @Data
		                    END
	                    END

	                    INSERT INTO #Burndown
	                    VALUES(@Data, @TotalPontos - @PontosPorDia * @Dia, @TotalPontos - @Valor)

	                    SET @Dia = @Dia + 1
	                    SET @Data = DATEADD(d, @Dia, @DataInicio)
                    END

                    SELECT Data, Planejado, Executado AS Queimado FROM #Burndown

                    DROP TABLE #Burndown
                    DROP TABLE #Log";

            return this.Listar<BurndownItem>(sql, parametros, this.PopularGraficoBurndown);

        }

        public void Adicionar(Quadro quadro)
        {
            quadro.DataCadastro = DateTime.Now;

            var parametros = new Dictionary<string, object>();
            parametros.Add("Nome", quadro.Nome);
            parametros.Add("Descricao", quadro.Descricao);
            parametros.Add("IdUsuario", quadro.CriadoPor.Id);
            parametros.Add("IdEquipe", quadro.Equipe.Id);
            parametros.Add("DataCadastro", quadro.DataCadastro);

            int id = Convert.ToInt32(this.Adicionar<Quadro>(parametros));

            quadro.Id = id;
        }

        public void Atualizar(Quadro quadro)
        {
            var parametros = new Dictionary<string, object>();
            parametros.Add("Nome", quadro.Nome);
            parametros.Add("Descricao", quadro.Descricao);
            parametros.Add("Arquivado", quadro.Arquivado);
            parametros.Add("Excluido", quadro.Excluido);
            this.Atualizar<Quadro>(quadro.Id, parametros);
        }

        public List<Quadro> Listar()
        {
            string sql = "SELECT Id, IdUsuario, IdEquipe, Nome, Descricao, DataInicio, DataFim, DataCadastro FROM [PREFIXO_TABELA]Quadro";
            var parametros = new Dictionary<string, object>();

            return this.Listar<Quadro>(sql, parametros, this.PopularObjeto);
        }

        public Quadro ObterPorId(int id)
        {
            string sql = "SELECT Id, IdUsuario, IdEquipe, Nome, Descricao, DataInicio, DataFim, DataCadastro, Chave FROM [PREFIXO_TABELA]Quadro WHERE Id = @Id";
            var parametros = new Dictionary<string, object>();
            parametros.Add("Id", id);
            return this.Obter<Quadro>(sql, parametros, this.PopularObjeto);
        }

        public Quadro ObterPorChave(string chave)
        {
            string sql = "SELECT Id, IdUsuario, IdEquipe, Nome, Descricao, DataInicio, DataFim, DataCadastro, Chave FROM [PREFIXO_TABELA]Quadro WHERE Chave = @Chave";
            var parametros = new Dictionary<string, object>();
            parametros.Add("Chave", chave);
            return this.Obter<Quadro>(sql, parametros, this.PopularObjeto);
        }

        public void Remover(int id)
        {
            this.Remover<Quadro>(id);
        }

        private Quadro PopularObjeto(SqlDataReader leitor)
        {
            var quadro = new Quadro();
            quadro.Id = leitor.GetInt32(0);
            quadro.CriadoPor = new Usuario();
            quadro.CriadoPor.Id = leitor.GetInt32(1);
            quadro.Equipe = new Equipe();
            quadro.Equipe.Id = leitor.GetInt32(2);
            quadro.Nome = leitor.GetString(3);
            quadro.Descricao = leitor.GetValueOrDefault<string>(4);
            
            quadro.DataCadastro = leitor.GetDateTime(7);


            if (leitor.FieldCount > 8)
            {
                quadro.Chave = leitor.GetValue(8).ToString();
            }

            return quadro;
        }

        private BurndownItem PopularGraficoBurndown(SqlDataReader leitor)
        {
            var item = new BurndownItem();
            item.Data = leitor.GetDateTime(0);
            item.Planejado = leitor.GetDecimal(1);
            item.FaltaQueimar = leitor.IsDBNull(2) ? null : leitor.GetDecimal(2) as decimal?;
            return item;
        }

        public List<Quadro> ListarPorUsuario(string nomeUsuario, bool? arquivado)
        {
            string sql = @"DECLARE @IsMaster BIT
                            DECLARE @IdUsuario INT

                            SET @IsMaster = 0

                            SELECT @IdUsuario = Id FROM [PREFIXO_TABELA]Usuario WHERE Nome = @Nome

                            IF EXISTS(SELECT * FROM [PREFIXO_TABELA]Usuario WHERE Id = @IdUsuario AND Permissoes LIKE '%Master%')  BEGIN
	                            SET @IsMaster = 1
                            END 


                            SELECT q.Id, q.IdUsuario, q.IdEquipe, q.Nome, q.Descricao, q.DataInicio, q.DataFim, q.DataCadastro
                            FROM [PREFIXO_TABELA]Quadro q 
                            LEFT JOIN [PREFIXO_TABELA]Equipe e
                            ON q.IdEquipe = e.Id
                            LEFT JOIN [PREFIXO_TABELA]EquipeUsuario p
                            ON p.IdEquipe = e.Id AND p.IdUsuario = @IdUsuario
                            WHERE (p.IdUsuario IS NOT NULL OR e.IdUsuario = @IdUsuario OR @IsMaster = 1 OR (q.IdUsuario = @IdUsuario AND q.IdEquipe = 0))
                            AND (q.Arquivado = @Arquivado OR @Arquivado IS NULL) AND q.Excluido = 0 AND (e.Excluido = 0 OR e.Excluido IS NULL)

                            ORDER BY q.Nome";

            var parametros = new Dictionary<string, object>();
            parametros.Add("Nome", nomeUsuario);
            parametros.Add("Arquivado", arquivado);

            return this.Listar<Quadro>(sql, parametros, this.PopularObjeto);
        }
    }
}
